package alipay

import (
	"context"
	"encoding/json"
	"errors"
	"github.com/go-pay/gopay/pkg/util"
	"github.com/gogap/logs"
	"io/ioutil"
	"log"
	"time"
	"yundian/internel/app/dao/memberdao"
	"yundian/internel/app/helper"
	"yundian/internel/app/models/membermodel"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/utils"
)

// 支付宝登录签名
func AuthLoginSing(appId string) (string, string, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝登录签名 获取应用密钥失败", err.Error())

	}

	privateKey := string(file)
	client := NewClient(appId, privateKey, true)
	return client.GetAliSing()
}

//支付宝登录 alipay.system.oauth.token 换取授权访问令牌
func AuthToken(authCode, appId string) (*GetAuthTokenResponse, error) {

	//authCode = "4b203fe6c11548bcabd8da5bb087a83b"

	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())

	}
	// 请求参数
	privateKey := string(file)
	client := NewClient(appId, privateKey, true)
	logs.Info("登录=====>", privateKey, appId, global.Cfg.Ali.PrivateKey)
	bm := make(BodyMap)
	bm.Set("grant_type", "authorization_code")
	bm.Set("code", authCode)
	bs, err := client.DoAliPay(bm, "alipay.system.oauth.token")
	if err != nil {
		log.Println("请求支付宝登录失败1", err.Error())
		return nil, err
	}
	logs.Info("222222222", string(bs))
	aliRsp := GetAuthTokenResponse{}
	if err = json.Unmarshal(bs, &aliRsp); err != nil {
		log.Println("请求支付宝登录失败2", err.Error())
		return nil, err
	}
	if aliRsp.ErrorResponse.Code != "10000" && aliRsp.ErrorResponse.Code != "" {

		log.Println("请求失败", aliRsp.ErrorResponse)
		return &aliRsp, errors.New(aliRsp.ErrorResponse.SubMsg)
	}

	signData, signDataErr := client.GetSignData(bs, "")
	//aliRsp.SignData = signData
	//校验签名
	verifySignErr := client.AutoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
	if verifySignErr != nil {
		log.Println("校验签名失败", verifySignErr.Error())

		return nil, err
	}
	return &aliRsp, nil
}

func Login(authData *GetAuthTokenResponse, appId string) (*LoginResponse, error) {
	var (
		tokenKey, token, unionid string
		err                      error
	)
	// ZM-Applet-Login-Token
	tokenKey = utils.Join(global.Const.Pre.TokenKeyPre, "-Zfb-Login-Token", authData.Response.OpenId)
	rdbSessionKey := utils.Join(authData.Response.OpenId, "-sessionKey") // 保存sessionKey用于解密
	global.Rdb.Set(context.Background(), rdbSessionKey, authData.Response.AccessToken, time.Hour*24)

	//查询支付宝密钥
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝授权,获取应用密钥失败", err.Error())

	}
	// 请求参数
	privateKey := string(file)
	client := NewClient(appId, privateKey, true)

	bm := make(BodyMap)
	bs, err := client.DoAliPay(bm, "alipay.user.info.share", authData.Response.AccessToken)

	userInfo := GetUserInfoShareResponse{}
	if err = json.Unmarshal(bs, &userInfo); err != nil {
		log.Println("请求支付宝会员授权信息查询接口失败", err.Error())
		return nil, err
	}
	if userInfo.UserInfoShareResponse.Code != "10000" {

		log.Println("请求失败", userInfo.UserInfoShareResponse.Msg, userInfo.UserInfoShareResponse.Code, userInfo.UserInfoShareResponse.SubMsg)
		return nil, errors.New(userInfo.UserInfoShareResponse.SubMsg)
	}
	logs.Info("3333=======>", userInfo)
	// 校验用户是否存在
	memInfo := memberdao.NewMemberDao().
		GetMemberInfoByOpenidAndAppId(authData.Response.OpenId, appId).Unwrap().(*membermodel.MembersModel)

	if memInfo.ID > 0 {
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "")
		unionid = memInfo.Unionid
	} else {
		unionid = util.GetRandomString(32)
		// 新增用户
		m := membermodel.New().Mutate(
			membermodel.WithXcxOpenid(authData.Response.OpenId),
			membermodel.WithUnionid(unionid),
			membermodel.WithRegFrom("aliPay_xcx"),
			membermodel.WithCreateAt(dingo.Time(time.Now().Unix())),
			membermodel.WithUUID(utils.Str2Md5(helper.GenerateUUID())),
			membermodel.WithAppId(appId),
			membermodel.WithNickName(userInfo.UserInfoShareResponse.NickName),
			membermodel.WithProvince(userInfo.UserInfoShareResponse.Province),
			membermodel.WithCity(userInfo.UserInfoShareResponse.City),
			membermodel.WithHeadimgurl(userInfo.UserInfoShareResponse.Avatar),
		)
		memInfo := memberdao.NewMemberDao().InsertMember(m).Unwrap().(*membermodel.MembersModel)
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "") // 生成token
	}

	// 将token保存到redis
	global.Rdb.Set(context.Background(), tokenKey, token, time.Hour*24) // 过期时间18小时
	resp := LoginResponse{}
	resp.Token = token
	resp.Code = userInfo.UserInfoShareResponse.Code
	resp.Msg = userInfo.UserInfoShareResponse.Msg
	resp.UnionId = unionid
	resp.UserId = userInfo.UserInfoShareResponse.Openid
	resp.NickName = userInfo.UserInfoShareResponse.NickName
	resp.Avatar = userInfo.UserInfoShareResponse.Avatar
	resp.Openid = userInfo.UserInfoShareResponse.Openid
	//resp.ErrorResponse = authData.ErrorResponse
	return &resp, err

}

func AccountsLogin(authData *GetAuthTokenResponse, appId string) (*LoginResponse, error) {
	var (
		tokenKey, token, unionid string
		err                      error
	)
	tokenKey = utils.Join(global.Const.Pre.TokenKeyPre, "-Zfb-Login-Token", authData.Response.UserId)

	// 校验用户是否存在
	memInfo := memberdao.NewMemberDao().
		GetMemberInfoByOpenidAndAppId(authData.Response.UserId, appId).Unwrap().(*membermodel.MembersModel)

	if memInfo.ID > 0 {
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "")
		unionid = memInfo.Unionid
	} else {
		return nil, nil
	}

	// 将token保存到redis
	global.Rdb.Set(context.Background(), tokenKey, token, time.Hour*24) // 过期时间18小时
	resp := LoginResponse{}
	resp.Token = token
	resp.UnionId = unionid
	resp.UserId = memInfo.XcxOpenid
	resp.NickName = memInfo.NickName
	resp.Avatar = memInfo.Headimgurl
	//resp.ErrorResponse = authData.ErrorResponse
	return &resp, err

}
